package libs

import (
	"errors"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/locales/en"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	enTranslations "github.com/go-playground/validator/v10/translations/en"
	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
	"reflect"
	"regexp"
)

var trans ut.Translator // 全局验证器

var validate *validator.Validate //validator.Validate实例

type translation struct {
	tag             string
	translation     string
	override        bool
	customRegisFunc validator.RegisterTranslationsFunc
	customTransFunc validator.TranslationFunc
}

// init 初始化验证器
func init() {
	var ok bool
	var locale string = "zh"
	//获取validator.Validate实例
	if validate, ok = binding.Validator.Engine().(*validator.Validate); !ok {
		panic("Failed to initialize the validator")
	}
	//注册自定义验证消息
	registerValidation()
	//注册自定义标签获取函数，以便从结构体字段中提取标签
	validate.RegisterTagNameFunc(func(field reflect.StructField) string {
		label := field.Tag.Get("label")
		if label == "" {
			label = field.Tag.Get("json")
			if label == "" {
				label = field.Tag.Get("form")
			}
		}

		if label == "-" {
			return ""
		}
		if label == "" {
			return field.Name
		}
		return label
	})
	//创建一个支持多种语言的翻译器。
	zhT := zh.New() // 中文翻译器
	enT := en.New() // 英文翻译器
	uni := ut.New(enT, zhT, enT)
	trans, ok = uni.GetTranslator(locale)
	if !ok {
		panic("Initialize a language not supported by the validator")
	}
	var err error
	// 注册翻译器
	switch locale {
	case "en":
		err = enTranslations.RegisterDefaultTranslations(validate, trans)
	case "zh":
		err = zhTranslations.RegisterDefaultTranslations(validate, trans)
	default:
		err = enTranslations.RegisterDefaultTranslations(validate, trans)
	}
	if err != nil {
		panic("Failed to register translator when initializing validator")
	}
	// 注册自定义语言翻译
	err = customRegisTranslation()
	if err != nil {
		panic("Failed to register translator when initializing validator")
	}
}

// registerValidation 注册自定义验证
func registerValidation() {
	var err error
	// 手机号验证规则
	err = validate.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
		return regexp.MustCompile(`^1[3456789]\d{9}$`).MatchString(fl.Field().String())
	})
	if err != nil {
		panic("Failed to register the mobile phone number verification rule")
	}

	// 验证用户名
	err = validate.RegisterValidation("username", func(fl validator.FieldLevel) bool {
		return regexp.MustCompile(`^[a-zA-Z0-9_-]+$`).MatchString(fl.Field().String())
	})
	if err != nil {
		panic("Failed to register the username verification rule")
	}

	// 日期验证规则
	err = validate.RegisterValidation("date", func(fl validator.FieldLevel) bool {
		return regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`).MatchString(fl.Field().String())
	})
	if err != nil {
		panic("Failed to register the date verification rule")
	}
}

// customRegisTranslation 自定义翻译
func customRegisTranslation() error {
	translations := []translation{
		{
			tag:         "mobile",
			translation: "{0}格式不正确",
			override:    false,
		},
		{
			tag:         "password",
			translation: "{0}格式不正确，必须包含大小写字母和数字",
			override:    false,
		},
		{
			tag:         "date",
			translation: "{0}格式不正确",
			override:    false,
		},
	}

	return registerTranslation(translations)
}

// registerTranslation 注册翻译
func registerTranslation(translations []translation) (err error) {
	registrationFunc := func(tag string, translation string, override bool) validator.RegisterTranslationsFunc {
		return func(ut ut.Translator) (err error) {
			if err = ut.Add(tag, translation, override); err != nil {
				return
			}
			return
		}
	}

	translateFunc := func(ut ut.Translator, fe validator.FieldError) string {
		t, err := ut.T(fe.Tag(), fe.Field())
		if err != nil {
			return fe.(error).Error()
		}
		return t
	}

	for _, t := range translations {
		if t.customTransFunc != nil && t.customRegisFunc != nil {
			err = validate.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc)
		} else if t.customTransFunc != nil && t.customRegisFunc == nil {
			err = validate.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc)
		} else if t.customTransFunc == nil && t.customRegisFunc != nil {
			err = validate.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc)
		} else {
			err = validate.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc)
		}

		if err != nil {
			return
		}
	}
	return
}

// CheckRequest 参数验证
func CheckRequest(err error) string {
	var errorMsg string
	var errs validator.ValidationErrors
	if errors.As(err, &errs) {
		fields := errs.Translate(trans)
		for _, err := range fields {
			errorMsg = err
			break
		}
	}
	return errorMsg
}
